package com.ojoin.trade.bpm.web.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLStreamException;

import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.ojoin.trade.bpm.web.domain.ProcessDefinitionVO;
import com.ojoin.trade.bpm.web.domain.ProcessInstanceVO;
import com.ojoin.trade.bpm.web.service.BpmProcessService;
import com.ojoin.trade.bpm.web.support.Page;
import com.ojoin.trade.common.web.controller.SimpleBaseController;
import com.ojoin.trade.common.web.domain.Result;
import com.ojoin.trade.common.web.domain.Result.Status;

/**
 * 流程定义相关Controller
 */
@Controller
@RequestMapping(value = "/bpm/process")
public class BpmProcessController extends SimpleBaseController {

	@Autowired
	private BpmProcessService bpmProcessService;

	/**
	 * 流程定义列表
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping("list")
	public Result processList(String category) {
		Page<ProcessDefinitionVO> page = new Page<ProcessDefinitionVO>();
	    bpmProcessService.processList(page, category);
		return new Result(Status.OK,page.convert());
	}
	
	/**
	 * 运行中的实例列表
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "running")
	public Result runningList(String procInsId, String procDefKey, Pageable fpage) throws IllegalAccessException, InvocationTargetException {
		Page<ProcessInstance> page = new Page<ProcessInstance>();
		page.setPageNo(fpage.getPageNumber());
		page = bpmProcessService.runningList(page, procInsId, procDefKey);
	    Page<ProcessInstanceVO> pageVO=new Page<ProcessInstanceVO>();
	    pageVO.setPageNo(fpage.getPageNumber());
	    
	    List<ProcessInstance> piList= page.getList();
	    List<ProcessInstanceVO> piVOList=new ArrayList<ProcessInstanceVO>() ;
	    for(ProcessInstance pi:piList){
	    	ProcessInstanceVO vo=new ProcessInstanceVO();
	    	BeanUtils.copyProperties(vo, pi);
	    	piVOList.add(vo);
	    }
	    
	    pageVO.setCount(page.getCount());
	    pageVO.setList(piVOList);
	    return new Result(Status.OK,pageVO.convert());
	}

	/**
	 * 读取资源，通过部署ID
	 * @param processDefinitionId  流程定义ID
	 * @param processInstanceId 流程实例ID
	 * @param resourceType 资源类型(xml|image)
	 * @param response
	 * @throws Exception
	 */
	@RequiresPermissions("bpm:process:edit")
	@RequestMapping(value = "resource/read")
	public void resourceRead(String procDefId, String proInsId, String resType, HttpServletResponse response) throws Exception {
		InputStream resourceAsStream = bpmProcessService.resourceRead(procDefId, proInsId, resType);
		byte[] b = new byte[1024];
		int len = -1;
		while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
			response.getOutputStream().write(b, 0, len);
		}
	}

	 
	
	/**
	 * 部署流程 - 保存
	 * @param file
	 * @return
	 */
	@RequiresPermissions("bpm:process:edit")
	@RequestMapping(value = "/deploy", method=RequestMethod.POST)
	public Result deploy(String category, MultipartFile file) {
		String fileName = file.getOriginalFilename();
		Result ret=new Result();
		if (StringUtils.isBlank(fileName)){
			ret.setMessage("请选择要部署的流程文件");
		}else{
			String message = bpmProcessService.deploy(category, file);
			ret.setMessage(message);
		}

		return new Result(Status.OK,ret);
	}
	
	/**
	 * 设置流程分类
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "updateCategory")
	public Result updateCategory(String procDefId, String category) {
		bpmProcessService.updateCategory(procDefId, category);
		return new Result(Status.OK,"设置流程分类完成");
	}

	/**
	 * 挂起、激活流程实例
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "update/{state}")
	public Result updateState(@PathVariable("state") String state, String procDefId) {
		String message = bpmProcessService.updateState(state, procDefId);
		return new Result(Status.OK,message);
	}
	
	/**
	 * 将部署的流程转换为模型
	 * @param procDefId
	 * @param redirectAttributes
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws XMLStreamException
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "convert/toModel")
	public Result convertToModel(String procDefId, RedirectAttributes redirectAttributes) throws UnsupportedEncodingException, XMLStreamException {
		org.activiti.engine.repository.Model modelData = bpmProcessService.convertToModel(procDefId);
		return new Result(Status.OK,"转换模型成功，模型ID="+modelData.getId());
	}
	
	/**
	 * 导出图片文件到硬盘
	 */
	@RequiresPermissions("bpm:process:edit")
	@RequestMapping(value = "export/diagrams")
	@ResponseBody
	public List<String> exportDiagrams(@Value("#{APP_PROP['activiti.export.diagram.path']}") String exportDir) throws IOException {
		List<String> files = bpmProcessService.exportDiagrams(exportDir);;
		return files;
	}

	/**
	 * 删除部署的流程，级联删除流程实例
	 * @param deploymentId 流程部署ID
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "delete")
	public Result delete(String deploymentId) {
		bpmProcessService.deleteDeployment(deploymentId);
		return new Result(Status.OK,"删除流程定义完成");
	}
	
	/**
	 * 删除流程实例
	 * @param procInsId 流程实例ID
	 * @param reason 删除原因
	 */
	@RequiresPermissions("bpm:process:edit")
	@ResponseBody
	@RequestMapping(value = "deleteProcIns")
	public Result deleteProcIns(String procInsId, String reason, RedirectAttributes redirectAttributes) {
		if (StringUtils.isBlank(reason)){
			return new Result(Status.ERROR,"请填写删除原因");
		}else{
			bpmProcessService.deleteProcIns(procInsId, reason);
		}
		return new Result(Status.OK,"删除流程实例成功");
	}
	
}
